//----------------------------------------------------------------------------------------
// @Project Includes
#include "includes.h"

//----------------------------------------------------------------------------------------
// @Local Macro Define in the module

//----------------------------------------------------------------------------------------
// @Local Type defines in the module

//----------------------------------------------------------------------------------------
// @Global Variables define in the module
uint16_t  g_u16RegParm[COSM_REG_PARM_MAX_NUM] ={0};

//----------------------------------------------------------------------------------------
// @Prototypes of functions in the module
static void srv_cosm_printfData(uint8_t *buffer,uint16_t len);
static void srv_cosm_sendPacket(uint8_t *_buf, uint16_t _len);

static void srv_cosm_writeRegParmErrAck(uint16_t addr, uint16_t reglen);
static void srv_cosm_ctlCmdAnaly(uint16_t cmd);
static void srv_cosm_writeRegParmAck(uint16_t addr, uint16_t reglen);
static void srv_cosm_readRegParmErrAck(uint16_t addr, uint16_t reglen);
static void srv_cosm_readRegParmAck(uint16_t addr, uint16_t reglen);
static void srv_cosm_readRegRealtimeAck(uint16_t addr, uint16_t reglen);

static void srv_cosm_read(void);
static void srv_cosm_write(void);	
static void srv_cosm_analyze(void);
static void srv_cosm_poll(void);

//========================================================================================
static void srv_cosm_printfData(uint8_t *buffer,uint16_t len)
{
    uint16_t i = 0;
    if(len > 512)
    {
				printf("\r\n");
        return;
    }

    printf("\r\n");
    for(i = 0; i < len;i++)
    {
        printf("%02x ",buffer[i]);
    }
    printf("\r\n");
}

/**
 * @brief  cosm send packet
 * @param  buf: the data
 *         len:the data len
 * @return 
 * @note   
 */
static void srv_cosm_sendPacket(uint8_t *_buf, uint16_t _len)
{
		if (g_stcUart.stcSif1.brxCompleteFlg)
		{
//			RS485_SEND();
			drv_usart_sendData(USART_SIF1_INDEX, (void *)_buf, _len);
			printf("SIF1:<< TxLen = %d; TX:",_len);
			srv_cosm_printfData((void *)_buf, _len);		
		}	
		if (g_stcUart.stcSif2.brxCompleteFlg)
		{
//			RS485_SEND();
			drv_usart_sendData(USART_SIF2_INDEX, (void *)_buf, _len);
			printf("SIF2:<< TxLen = %d; TX:",_len);
			srv_cosm_printfData((void *)_buf, _len);		
		}		
		if (g_stcUart.stcRs485.brxCompleteFlg)
		{		
//			RS485_SEND();
			drv_usart_sendData(USART_RS485_INDEX, (void *)_buf, _len);
			MODBUS_DEBUG("Modbus:<< TxLen = %d; TX:",_len);
			srv_cosm_printfData((void *)_buf, _len);	
		}
}
/**
 * @brief  write parm err ack
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_writeRegParmErrAck(uint16_t addr, uint16_t reglen)
{
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
    uint8_t u8crc = 0;
		
    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_WRITE;
    u8TxBuf[u16count++] = COSM_WRITE_STATE_ADDRESS_ERROR;
	
    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		
}

/**
 * @brief  ctl cmd analy
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_ctlCmdAnaly(uint16_t cmd)
{
		switch (cmd)
		{
				case COSM_CMD_SHUTDOWN:
						srv_event_save(EVENT_TYPE_CMD , 0);	
						break;
				case COSM_CMD_DEFAULTFACTORY:
						srv_parm_defaultFactory(1);
						break;
				case COSM_CMD_RESET:
						NVIC_SystemReset();
						break;
				case COSM_CMD_PDSG:
//            if (g_stcVar.bpdsgMosCtl== true)
//            {
//								g_stcVar.bpdsgMosCtl = false;
//								PDSG_RESET();
//            }
//            else
//            {					
//								g_stcVar.bpdsgMosCtl = true;
//								PDSG_SET();
//            }						
						break;				
				case COSM_CMD_CHGSWITCH:
            if (g_stcVar.bchgMosCmdCtl== true)
            {
								g_stcVar.bchgMosCmdCtl = false;
            }
            else
            {					
								g_stcVar.bchgMosCmdCtl = true;
            }					
						break;
				case COSM_CMD_DSGSWITCH:
            if (g_stcVar.bdsgMosCmdCtl== true)
            {
								g_stcVar.bdsgMosCmdCtl = false;
            }
            else
            {					
								g_stcVar.bdsgMosCmdCtl = true;
            }						
						break;
				case COSM_CMD_DELEVENT:
						srv_event_delete();
						break;	
				case COSM_CMD_ENTERTEST:
						g_stcVar.bpvt = true;
						srv_parm_defaultFactory(0);
						break;	
				case COSM_CMD_EXITTEST:
						g_stcVar.bpvt = false;
						break;
				case COSM_CMD_SLEEP:
						g_stcVar.bcmdSleep = true;
						break;
				case COSM_CMD_POWERDOWN:
						g_stcVar.bcmdPowerDown = true;
						break;
				case COSM_CMD_CLEFAULT:
						break;
				case COSM_CMD_SOC:
						break;
				case COSM_CMD_HEAT:
//			      if (g_stcVar.bheatCmd== true)
//			      {
//								g_stcVar.bheatCmd = false;
//								HTR_RESET();
//								g_stcVar.bheatFlag = false;
//			      }
//			      else
//			      {					
//								g_stcVar.bheatCmd = true;
//								HTR_SET();
//								g_stcVar.bheatFlag = true;
//			      }					
						break;	
				case COSM_CMD_PCHG:
//            if (g_stcVar.bpchgMosCtl== true)
//            {
//								g_stcVar.bpchgMosCtl = false;
//								PCHG_RESET();
//            }
//            else
//            {					
//								g_stcVar.bpchgMosCtl = true;
//								PCHG_SET();
//            }						
						break;	
				case COSM_CMD_CLIMIT:
						break;					
				default:
						break;
		}
    			
}

/**
 * @brief  write parm ack
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_writeRegParmAck(uint16_t addr, uint16_t reglen)
{
    uint8_t writeBuf[UPDATE_TAG_SIZE] = {0};
    uint8_t readBuf[UPDATE_TAG_SIZE] = {0};
		
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
		uint16_t u16i = 0;
    uint8_t u8crc = 0;
	  uint16_t u16ctlcmd = 0;
    uint16_t i = 0;	
	
    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_WRITE;
    u8TxBuf[u16count++] = COSM_WRITE_STATE_SUCCESS;
	
	  if (addr == REG_BASIC_RTC_TIME)
		{
				drv_rtc_setTime(&g_stcUart.stcRs485.u8rxBackbuff[7]);
		}
		else if (addr == COSM_CTL_ADDR)
		{
				u16ctlcmd = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[7] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[8]));
			  srv_cosm_ctlCmdAnaly(u16ctlcmd);
		}
		else if (addr == COSM_BAL_ADDR)
		{
				g_stcVar.u32cmdBal = (((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[9] << 24) | 
			                        ((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[10] << 16) | 
															((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[7] << 8) | 
															((uint32_t)g_stcUart.stcRs485.u8rxBackbuff[8] << 0)  
															);
		}
		else if (addr == COSM_OTA_INFO_ADDR)
		{
				writeBuf[0] = 0x5A;
				writeBuf[1] = 0xA5;
				memcpy(&writeBuf[2],&g_stcUart.stcRs485.u8rxBackbuff[7],9); 
			
				drv_flash_write(writeBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);
				drv_flash_read(readBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);
				for (i = 0; i < UPDATE_TAG_SIZE; i++)
				{
						if (writeBuf[i] != readBuf[i])
						{
								MODBUS_DEBUG("Modbus:<< OTA write update data error!g_stcVar.m_stcUpgInfo[%d]=0x%0x tempBuf[%d]=0x%0x\r\n", i, writeBuf[i], i, readBuf[i]);
								memset((void *) writeBuf, 0x00, 11);
								drv_flash_write(writeBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);
								return ; 
						}
				}

				MODBUS_DEBUG("Modbus:<< goto boot upgrade, restart and enter BOOT....\r\n ");
				drv_systick_delay_ms(2);
				NVIC_SystemReset();
		}
		
		else
		{
			for (u16i = 0; u16i < reglen; u16i++)
			{
					g_u16RegParm[addr + u16i] = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[7+2*u16i] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[8+2*u16i]));
			}

			g_stcVar.bparmWriteFlag = true;
			g_stcVar.u16parmWriteWaitTime = PARM_WRITE_MAX_WAIT_TIME;			
		}
		
    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		
}

/**
 * @brief  read parm err ack
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_readRegParmErrAck(uint16_t addr, uint16_t reglen)
{
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
		uint16_t u16len = 0;
    uint8_t u8crc = 0;

    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_READ;
		u16len = reglen*2;
	
		u8TxBuf[u16count++] = u16len >> 8;
    u8TxBuf[u16count++] = u16len >> 0;
	
		u8TxBuf[u16count++] = addr >> 8;
    u8TxBuf[u16count++] = addr >> 0;

    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		
}

/**
 * @brief  read parm ack
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_readRegParmAck(uint16_t addr, uint16_t reglen)
{
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
		uint16_t u16len = 0;
		uint16_t u16i = 0;
    uint8_t u8crc = 0;
	
    uint16_t ui16Index = 0;	
    uint32_t ui32Address = 0;	

    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_READ;
	
	  if (addr == COSM_EVENT_INDEX_ADDR)
		{
				u16len = reglen*2;
			
				u8TxBuf[u16count++] = u16len >> 8;
				u8TxBuf[u16count++] = u16len >> 0;
			
				srv_event_indexSearch();
				u8TxBuf[u16count++] = g_stcEvent.u16index>> 8;	
				u8TxBuf[u16count++] = g_stcEvent.u16index;			
		}
		else if(addr == COSM_EVENT_DATA_ADDR)
		{
				u16len = 110;
			
				u8TxBuf[u16count++] = u16len >> 8;
				u8TxBuf[u16count++] = u16len >> 0;
			
				u8TxBuf[u16count++] = g_stcUart.stcRs485.u8rxBackbuff[7];	
				u8TxBuf[u16count++] = g_stcUart.stcRs485.u8rxBackbuff[8];
				ui16Index = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[7] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[8]));
			
				if(ui16Index >= EVENT_SAVE_TOTAL_SIZE/EVENT_SAVE_UNIT_SIZE)
				{
						return;
				}
			
				ui32Address = g_stcEvent.u32addrStart+ui16Index*EVENT_SAVE_UNIT_SIZE;
			
				if(ui32Address >= EVENT_SAVE_START_ADDR+EVENT_SAVE_TOTAL_SIZE)
				{ 
						ui32Address-=EVENT_SAVE_TOTAL_SIZE;
				}
			
				drv_flash_read(&u8TxBuf[u16count], ui32Address+2, 108);  
				u16count += 108;			
		}
		else
		{
				u16len = reglen*2;
			
				u8TxBuf[u16count++] = u16len >> 8;
				u8TxBuf[u16count++] = u16len >> 0;
			
				srv_parm_readRegRefresh();
				for (u16i = 0; u16i < reglen; u16i++)           
				{
						u8TxBuf[u16count++] = g_u16RegParm[addr + u16i] >> 8;
						u8TxBuf[u16count++] = g_u16RegParm[addr + u16i] >> 0;
				}
		}

    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		
}

/**
 * @brief  read real time ack
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_readRegRealtimeAck(uint16_t addr, uint16_t reglen)
{
    uint8_t u8TxBuf[COSM_TX_BUF_SIZE];
    uint16_t u16count = 0;
		uint16_t u16len = 0;
		uint32_t u32temp = 0;
		uint16_t u16i = 0;
    uint8_t u8crc = 0;

    u16count = 0;
    u8TxBuf[u16count++] = COSM_PROTOCOL_HEAD;
		u8TxBuf[u16count++] = COSM_PROTOCOL_ADDRESS;
    u8TxBuf[u16count++] = COSM_PROTOCOL_READ;
		u16len = reglen*2;
	
		u8TxBuf[u16count++] = u16len >> 8;
    u8TxBuf[u16count++] = u16len >> 0;
	
	  u8TxBuf[u16count++] = g_stcVar.u16voltMax >> 8;
    u8TxBuf[u16count++] = g_stcVar.u16voltMax;
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcVar.u8voltMaxNum;	
	  u8TxBuf[u16count++] = g_stcVar.u16voltMin >> 8;
    u8TxBuf[u16count++] = g_stcVar.u16voltMin;
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcVar.u8voltMinNum;	
		
    u8TxBuf[u16count++] = ((int16_t)g_stcVar.i8tempMax+TEMP_OFFSET) >> 8;
    u8TxBuf[u16count++] = ((int16_t)g_stcVar.i8tempMax+TEMP_OFFSET) >> 0;
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcVar.u8maxTmprPos;			
    u8TxBuf[u16count++] = ((int16_t)g_stcVar.i8tempMin+TEMP_OFFSET) >> 8;
    u8TxBuf[u16count++] = ((int16_t)g_stcVar.i8tempMin+TEMP_OFFSET) >> 0;		
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcVar.u8minTmprPos;	

		for (u16i = 0; u16i < BMS_MAX_CELLNUM; u16i++)
		{
				u8TxBuf[u16count++] = g_stcVar.u16cellVolt[u16i] >> 8;
				u8TxBuf[u16count++] = g_stcVar.u16cellVolt[u16i];
		}
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = MAX_TMPR_NUM;	/*to define */
		for (u16i = 0; u16i < BMS_MAX_TEMPNUM; u16i++)
		{
			  u8TxBuf[u16count++] = 0;
        u8TxBuf[u16count++] = g_stcVar.i8cellTemp[u16i]+TEMP_OFFSET;
		}
		
		u32temp = 1000000 + (g_stcParm.stcConfig.u32designCap/2);
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0; 
		u32temp = 1000000 - (g_stcParm.stcConfig.u32designCap*2);
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16; 	
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0; 
		
    u8TxBuf[u16count++] = (g_stcVar.i32avgCurrent+1000000) >> 24;
    u8TxBuf[u16count++] = (g_stcVar.i32avgCurrent+1000000) >> 16;
    u8TxBuf[u16count++] = (g_stcVar.i32avgCurrent+1000000) >> 8;
    u8TxBuf[u16count++] = (g_stcVar.i32avgCurrent+1000000) >> 0;
    u8TxBuf[u16count++] = (g_stcVar.u32totalSumVolt) >> 24;
    u8TxBuf[u16count++] = (g_stcVar.u32totalSumVolt) >> 16;
    u8TxBuf[u16count++] = (g_stcVar.u32totalSumVolt) >> 8;
    u8TxBuf[u16count++] = (g_stcVar.u32totalSumVolt) >> 0;

		u32temp = ((uint64_t)abs(g_stcVar.i32avgCurrent) *(uint64_t)g_stcVar.u32totalSumVolt)/1000;
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16; 	
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0; 
		
	u8TxBuf[u16count++] = g_stcParm.stcConfig.u16cycleCount >> 8;
	u8TxBuf[u16count++] = g_stcParm.stcConfig.u16cycleCount;

    u8TxBuf[u16count++] = g_stcVar.u32balStat >> 8;
    u8TxBuf[u16count++] = g_stcVar.u32balStat;
    u8TxBuf[u16count++] = g_stcVar.u32balStat >> 24;
    u8TxBuf[u16count++] = g_stcVar.u32balStat >> 16;

    u8TxBuf[u16count++] = g_stcVar.unProtRank1.dword >> 8;
    u8TxBuf[u16count++] = g_stcVar.unProtRank1.dword;			
    u8TxBuf[u16count++] = g_stcVar.unProtRank1.dword >> 24;
    u8TxBuf[u16count++] = g_stcVar.unProtRank1.dword >> 16;

    u8TxBuf[u16count++] = g_stcVar.unProtRank2.dword >> 8;
    u8TxBuf[u16count++] = g_stcVar.unProtRank2.dword;			
    u8TxBuf[u16count++] = g_stcVar.unProtRank2.dword >> 24;
    u8TxBuf[u16count++] = g_stcVar.unProtRank2.dword >> 16;

    u8TxBuf[u16count++] = g_stcVar.unProtRank3.dword >> 8;
    u8TxBuf[u16count++] = g_stcVar.unProtRank3.dword;			
    u8TxBuf[u16count++] = g_stcVar.unProtRank3.dword >> 24;
    u8TxBuf[u16count++] = g_stcVar.unProtRank3.dword >> 16;

		memset(&u8TxBuf[u16count],0x00,8); /*to define */       
    u16count += 8; 
		
	  u8TxBuf[u16count++] = g_stcVar.u16voltDiff >> 8;
    u8TxBuf[u16count++] = g_stcVar.u16voltDiff;
		
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcVar.i8mosTemp + TEMP_OFFSET;		
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcVar.i8mosTemp + TEMP_OFFSET;		
	  u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcVar.i8ambTemp + TEMP_OFFSET;	
	  u8TxBuf[u16count++] = g_stcVar.u16canError >> 8;
    u8TxBuf[u16count++] = g_stcVar.u16canError >> 0;
		
    if(g_stcState.enstate == SST_CHG)
    {
        u8TxBuf[u16count++] =(g_stcSoc.u32chgRemainTime/60) >> 8;
        u8TxBuf[u16count++] = (g_stcSoc.u32chgRemainTime/60);     
    }
    else
    {
        u8TxBuf[u16count++] =(g_stcSoc.u32dsgRemainTime/60) >> 8;
        u8TxBuf[u16count++] = g_stcSoc.u32dsgRemainTime/60;       
    }

    if (false == srv_contactor_getState(CNT_CHG))
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x00;	        
    }
    else
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x01;       
    }		
    if (false == srv_contactor_getState(CNT_DSG))
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x00;	        
    }
    else
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x01;       
    }
    if (false == srv_contactor_getState(CNT_PCHG))
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x00;	        
    }
    else
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x01;       
    }
    if (false == srv_contactor_getState(CNT_PDSG))
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x00;	        
    }
    else
    {
        u8TxBuf[u16count++] = 0x00;
        u8TxBuf[u16count++] = 0x01;       
    }	

	  if((srv_signal_getChargeIn() == true)||(g_stcState.enstate == SST_CHG))	
		{
        g_stcVar.unmodleWorkState.bit.charge = 1;	
		}	
		else
		{
        g_stcVar.unmodleWorkState.bit.charge = 0;				
		}		
		if (abs(g_stcVar.i32avgCurrent) <= g_stcParm.stcConfig.u16curThr)
		{
				g_stcVar.unmodleWorkState.bit.bms = 0;
		}
    else if(g_stcState.enstate == SST_CHG)	
		{
        g_stcVar.unmodleWorkState.bit.bms = 1;	
		}	
		else
		{
        g_stcVar.unmodleWorkState.bit.bms = 2; 			
		}
		
//	  if(g_stcCommu.enState == SST_COMMU_CONNECT)	
//		{
//        g_stcVar.unmodleWorkState.bit.bt = 1;	
//		}	
//		else
//		{
//        g_stcVar.unmodleWorkState.bit.bt = 0;				
//		}			
    u8TxBuf[u16count++] = g_stcVar.unmodleWorkState.dword >> 8;
    u8TxBuf[u16count++] = g_stcVar.unmodleWorkState.dword;			
    u8TxBuf[u16count++] = g_stcVar.unmodleWorkState.dword >> 24;
    u8TxBuf[u16count++] = g_stcVar.unmodleWorkState.dword >> 16;		
	
    u8TxBuf[u16count++] = 0x00;
    u8TxBuf[u16count++] = 0x00;	
		
	  if (g_stcParm.stcConfig.u8capAutoLearn  == true)	
	  {
	      u8TxBuf[u16count++] = 0;	
	      u8TxBuf[u16count++] = 1; 
	  }
	  else
	  { 
	      u8TxBuf[u16count++] = 0;
	      u8TxBuf[u16count++] = 0;  
	  } 
	  u8TxBuf[u16count++] = 0;
	  u8TxBuf[u16count++] = 0; 
		
    u8TxBuf[u16count++] = (g_stcSoc.stcdata.u32displayValue/1000) >> 8;
    u8TxBuf[u16count++] = (g_stcSoc.stcdata.u32displayValue/1000) >> 0;
    u8TxBuf[u16count++] = (g_stcSoc.stcdata.u32trueValue/1000) >> 8;
    u8TxBuf[u16count++] = (g_stcSoc.stcdata.u32trueValue/1000) >> 0; 

    u8TxBuf[u16count++] = 0;
    u8TxBuf[u16count++] = g_stcParm.stcConfig.u8soh; 
		
		u32temp = g_stcParm.stcConfig.u32designCap;
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0; 
		u32temp = g_stcParm.stcConfig.u32fullChgCap;
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0; 
		
		u32temp = (((((uint64_t)g_stcParm.stcConfig.u32fullChgCap)/10)*(((uint64_t)g_stcSoc.stcdata.u32displayValue)/1000))/100);
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0;
		
		u32temp = (g_stcParm.stcConfig.u32fullChgCap)*(g_stcParm.stcConfig.u16cycleCount+1);
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0;		
		
		u32temp = ((g_stcParm.stcConfig.u32fullChgCap)*g_stcParm.stcConfig.u16cycleCount) +(((g_stcParm.stcConfig.u32fullChgCap/1000)*(g_stcSoc.stcdata.u32displayValue/1000)));
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0;	

		u32temp = g_stcParm.stcConfig.u32fullChgCap;
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0; 
		
	  u32temp = 0;
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0;

		u32temp = 0;
    u8TxBuf[u16count++] = u32temp >> 24;	
    u8TxBuf[u16count++] = u32temp >> 16;
    u8TxBuf[u16count++] = u32temp >> 8;	
    u8TxBuf[u16count++] = u32temp >> 0; 
		
		memset(&u8TxBuf[u16count],0x00,20);     
    u16count += 20; 
		
		memset(&u8TxBuf[u16count],0x00,102);     
    u16count += 102; 		

    u8crc = srv_crc8_cosm(&u8TxBuf[1], u16count-1);
		u8TxBuf[u16count++] = u8crc;
    u8TxBuf[u16count++] = COSM_PROTOCOL_TAIL;
		srv_cosm_sendPacket(u8TxBuf, u16count);
		
}


/**
 * @brief  cosm read
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_read(void)
{
		uint16_t u16regStartAddr = 0;	
		uint16_t u16regLen = 0;	
	
		u16regStartAddr = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[3] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[4]));
		u16regLen = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[5] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[6]));
	
	  if ((u16regStartAddr >= COSM_BASICINFO_START_ADDR)&&(u16regStartAddr <= COSM_BASICINFO_END_ADDR))/*the basic info data */
		{
			  if (u16regLen > (COSM_BASICINFO_END_ADDR - COSM_BASICINFO_START_ADDR) )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegParmAck(u16regStartAddr, u16regLen);
				}
		}
		else if ((u16regStartAddr >= COSM_REALTIME_START_ADDR)&&(u16regStartAddr <= COSM_REALTIME_END_ADDR))/*the realtime info data */
		{
			  if (u16regLen > (COSM_REALTIME_END_ADDR - COSM_REALTIME_START_ADDR) )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegRealtimeAck(u16regStartAddr, u16regLen);
				}			
		}
		else if ((u16regStartAddr >= COSM_CONFIGPARM_START_ADDR)&&(u16regStartAddr <= COSM_CONFIGPARM_END_ADDR))/*the sys parm info data */
		{
			  if (u16regLen > (COSM_CONFIGPARM_END_ADDR - COSM_CONFIGPARM_START_ADDR) )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegParmAck(u16regStartAddr, u16regLen);
				}			
		}	
		else if ((u16regStartAddr >= COSM_SWPROTECTPARM_START_ADDR)&&(u16regStartAddr <= COSM_SWPROTECTPARM_END_ADDR))/*the sw protect parm info data */
		{
			  if (u16regLen > (COSM_SWPROTECTPARM_END_ADDR - COSM_SWPROTECTPARM_START_ADDR) )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegParmAck(u16regStartAddr, u16regLen);
				}			
		}	
		else if ((u16regStartAddr >= COSM_HWPROTECTPARM_START_ADDR)&&(u16regStartAddr <= COSM_HWPROTECTPARM_END_ADDR))/*the hw protect parm info data */
		{
			  if (u16regLen > (COSM_HWPROTECTPARM_END_ADDR - COSM_HWPROTECTPARM_START_ADDR) )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegParmAck(u16regStartAddr, u16regLen);
				}			
		}	
		else if ((u16regStartAddr >= COSM_CALPARM_START_ADDR)&&(u16regStartAddr <= COSM_CALPARM_END_ADDR))/*the hw protect parm info data */
		{
			  if (u16regLen > (COSM_CALPARM_END_ADDR - COSM_CALPARM_START_ADDR) )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegParmAck(u16regStartAddr, u16regLen);
				}			
		}
		else if (u16regStartAddr == COSM_EVENT_INDEX_ADDR)
		{
			  if (u16regLen != 1 )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegParmAck(u16regStartAddr, u16regLen);
				}				
		}
		else if (u16regStartAddr == COSM_EVENT_DATA_ADDR)
		{
			  if (u16regLen != 1 )
        {
					  srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_readRegParmAck(u16regStartAddr, u16regLen);
				}				
		}		
		else
		{
			srv_cosm_readRegParmErrAck(u16regStartAddr, u16regLen);
		}
}

/**
 * @brief  cosm write
 * @param  
 * @return 
 * @note   
 */ 
static void srv_cosm_write(void)
{
		uint16_t u16regStartAddr = 0;	
		uint16_t u16regLen = 0;	
	
		u16regStartAddr = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[3] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[4]));
		u16regLen = (((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[5] << 8) | ((uint16_t)g_stcUart.stcRs485.u8rxBackbuff[6]));
	
	  if ((u16regStartAddr >= COSM_BASICINFO_START_ADDR)&&(u16regStartAddr <= COSM_BASICINFO_END_ADDR))/*the basic info data */
		{
			  if (u16regLen > (COSM_BASICINFO_END_ADDR - COSM_BASICINFO_START_ADDR) )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}
		}
		else if ((u16regStartAddr >= COSM_CONFIGPARM_START_ADDR)&&(u16regStartAddr <= COSM_CONFIGPARM_END_ADDR))/*the sys parm info data */
		{
			  if (u16regLen > (COSM_CONFIGPARM_END_ADDR - COSM_CONFIGPARM_START_ADDR) )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}			
		}	
		else if ((u16regStartAddr >= COSM_SWPROTECTPARM_START_ADDR)&&(u16regStartAddr <= COSM_SWPROTECTPARM_END_ADDR))/*the sw protect parm info data */
		{
			  if (u16regLen > (COSM_SWPROTECTPARM_END_ADDR - COSM_SWPROTECTPARM_START_ADDR) )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}			
		}	
		else if ((u16regStartAddr >= COSM_HWPROTECTPARM_START_ADDR)&&(u16regStartAddr <= COSM_HWPROTECTPARM_END_ADDR))/*the hw protect parm info data */
		{
			  if (u16regLen > (COSM_HWPROTECTPARM_END_ADDR - COSM_HWPROTECTPARM_START_ADDR) )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}			
		}	
		else if ((u16regStartAddr >= COSM_CALPARM_START_ADDR)&&(u16regStartAddr <= COSM_CALPARM_END_ADDR))/*the hw protect parm info data */
		{
			  if (u16regLen > (COSM_CALPARM_END_ADDR - COSM_CALPARM_START_ADDR) )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}			
		}
		else if (u16regStartAddr == COSM_CTL_ADDR)
		{
			  if (u16regLen != 1 )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}				
		}
		else if (u16regStartAddr == COSM_BAL_ADDR)
		{
			  if (u16regLen != 2 )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
				}			
		}
		else if (u16regStartAddr == COSM_OTA_INFO_ADDR)
		{
			  if (u16regLen != 9 )
        {
					  srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
				}
				else
				{
					  printf("Modbus:<<  ota info init \r\n");
						memset(&g_stcVar.stcUpgInfo,0x0,sizeof(stc_upginfo_t));
						memset(&g_stcVar.stcUpg,0x0,sizeof(stc_upg_t));
					
						srv_cosm_writeRegParmAck(u16regStartAddr, u16regLen);
						g_stcVar.stcUpg.state = OTA_STATE_START;
						g_stcVar.stcUpg.u8timeout = COSM_OTA_TIMEOUT;
				}			
		}		
		
		else
		{
			srv_cosm_writeRegParmErrAck(u16regStartAddr, u16regLen);
		}	
}

/**
 * @brief  cosm data analyze app
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_analyze(void)
{	
	  if (g_stcUart.stcRs485.u8rxBackbuff[2] == COSM_PROTOCOL_READ)
		{
				srv_cosm_read();
		}
		else if (g_stcUart.stcRs485.u8rxBackbuff[2] == COSM_PROTOCOL_WRITE)
		{
			  srv_cosm_write();
		}
		else
		{
				// todo
		}
}

/**
 * @brief  cosm data poll
 * @param  
 * @return 
 * @note   
 */
static void srv_cosm_poll(void)
{
    uint8_t crc1 = 0;
		uint8_t u8temp = 0;
		
    if (g_stcUart.stcRs485.vu32rxBackMQPush < 9)
    {
			  MODBUS_DEBUG("Modbus:<< the size error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
        g_stcUart.stcRs485.vu32rxBackMQPush = 0;	
        return;
    }
		
		if ((g_stcUart.stcRs485.u8rxBackbuff[0]!= COSM_PROTOCOL_HEAD)||
			  (g_stcUart.stcRs485.u8rxBackbuff[g_stcUart.stcRs485.vu32rxBackMQPush-1]!= COSM_PROTOCOL_TAIL)
		)
		{
				MODBUS_DEBUG("Modbus:<< the head and tail error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
        g_stcUart.stcRs485.vu32rxBackMQPush = 0;	
        return;			
		}
		
    if (g_stcUart.stcRs485.u8rxBackbuff[1] != COSM_PROTOCOL_ADDRESS)
    {
				MODBUS_DEBUG("Modbus:<< the address error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);			
        g_stcUart.stcRs485.vu32rxBackMQPush = 0;	
        return;
    }		
		
    crc1 = srv_crc8_cosm(&g_stcUart.stcRs485.u8rxBackbuff[1], g_stcUart.stcRs485.vu32rxBackMQPush - 3);
		u8temp = g_stcUart.stcRs485.u8rxBackbuff[g_stcUart.stcRs485.vu32rxBackMQPush - 2];
		
    if (crc1 != u8temp)
    {
				MODBUS_DEBUG("Modbus:<< the CRC error  crc1=%d RxCount = %d; RX:",crc1,g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
		}	
		else
		{	
				MODBUS_DEBUG("Modbus:<< the Modbus data format is correct, RxCount = %d; RX:",g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_printfData(g_stcUart.stcRs485.u8rxBackbuff, g_stcUart.stcRs485.vu32rxBackMQPush);
				srv_cosm_analyze();
		}
    	
		g_stcUart.stcRs485.vu32rxBackMQPush = 0;

}

/**
 * @brief  cosm receive process
 * @param  
 * @return 
 * @note   
 */
void srv_cosm_timeout(void)
{
    uint8_t writeBuf[UPDATE_TAG_SIZE] = {0};

    if (g_stcVar.stcUpg.u8timeout)
    {
        g_stcVar.stcUpg.u8timeout--;
			  if (g_stcVar.stcUpg.u8timeout == 0)
				{
					  printf("Modbus:<<  ota timeout \r\n");
						memset(&g_stcVar.stcUpgInfo,0x0,sizeof(stc_upginfo_t));
						memset(&g_stcVar.stcUpg,0x0,sizeof(stc_upg_t));	
					
						memset((void *) writeBuf, 0x00, 11);
						drv_flash_write(writeBuf, OTA_CONFIG_ADDR, UPDATE_TAG_SIZE);					
				}
    }
}

/**
 * @brief  cosm receive process
 * @param  
 * @return 
 * @note   
 */
void srv_cosm_receiveProcess(void)
{
    if (g_stcUart.stcRs485.brxCompleteFlg)		
    {
//        srv_cosm_poll();
//				g_stcUart.stcRs485.brxCompleteFlg = false;
			
				memcpy(&g_stcUart.stcRs485.u8rxBackbuff[0] ,&g_stcUart.stcRs485.u8rxbuff[0],g_stcUart.stcRs485.vu32rxMQPush);
				g_stcUart.stcRs485.vu32rxBackMQPush = g_stcUart.stcRs485.vu32rxMQPush;			
        srv_cosm_poll();
				g_stcUart.stcRs485.brxCompleteFlg = false;
				g_stcUart.stcRs485.vu32rxMQPush = 0;				
    }	
		
    if (g_stcUart.stcSif1.brxCompleteFlg)		
    {
				memcpy(&g_stcUart.stcRs485.u8rxBackbuff[0] ,&g_stcUart.stcSif1.u8rxbuff[0],g_stcUart.stcSif1.vu32rxMQPush);
				g_stcUart.stcRs485.vu32rxBackMQPush = g_stcUart.stcSif1.vu32rxMQPush;			
        srv_cosm_poll();
				g_stcUart.stcSif1.brxCompleteFlg = false;
				g_stcUart.stcSif1.vu32rxMQPush = 0;	
    }	
    if (g_stcUart.stcSif2.brxCompleteFlg)		
    {
				memcpy(&g_stcUart.stcRs485.u8rxBackbuff[0] ,&g_stcUart.stcSif2.u8rxbuff[0],g_stcUart.stcSif2.vu32rxMQPush);
				g_stcUart.stcRs485.vu32rxBackMQPush = g_stcUart.stcSif2.vu32rxMQPush;			
        srv_cosm_poll();
				g_stcUart.stcSif2.brxCompleteFlg = false;
				g_stcUart.stcSif2.vu32rxMQPush = 0;	
    }			
}

// =======================================================================================
// End of file.
// =======================================================================================
